package tcinert;
/*
 * Diplomova Prace: Vyuziti embedded modulu pro monitoring zivotnich funkci
 *                  pacienta 
 * Trida: Inicializace.java
 * Autor: Tomas Cinert 
 * Vytvoreno: 30.3.2012
 */

import com.siemens.icm.io.ATCommand;
import com.siemens.icm.io.ATCommandFailedException;
import com.siemens.icm.io.ATCommandResponseListener;
import java.io.IOException;
import java.util.Vector;
import com.siemens.icm.io.InPort;
import com.siemens.icm.io.InPortListener;
import com.siemens.icm.io.OutPort;
import tcinert.Stav;
/**
 * Trida Incializace slouzi pro nastaveni GSM modulu, listeneru na AT prikazy,
 * prip. nastaveni SPI, GPRS
 *
 * @author Tomas Cinert
 */
public class Inicializace {
    /*
     * ATCOmmands
     */
    ATCommand at = null;
    private ATCommandResponseListener listener = null;
    /*
     * GPIO
     */
    Vector vstupniPin;
    Vector vystupniPin;
    Vector uroven;
    InPort vstup;
    OutPort vystup;
    InPortListener vstupListener;
    /*
     * Pomocne pormenne
     */
    private boolean signal = false;
    private boolean komunikace = false;
    private int napetiBaterie=0;
    Stav prijem;
    Zaznam log;
    String docas=null;
    //datum=new DataParser();
    /**
     * Konstruktor - inicializace ATCommand - obsahuje anonnymni vnorenou tridu
     * - listener na odpoved ATprikazu
     *
     */
    public Inicializace(Stav prijem, Zaznam a) throws IllegalStateException, ATCommandFailedException, IOException {
        this.prijem = prijem;
        this.log=a;
        at = new ATCommand(false);


        listener = new ATCommandResponseListener() // Listener na odezvu na ATprikazy
        {

            public void ATResponse(String Response) {
                if (Response.startsWith("+CMEE: 0", 2)) {     // Pokud neni ulozen profil
                    inicializace();
                } else if (Response.startsWith("+CREG:", 2)) {
                    if (!Response.startsWith("+CREG: 0,1", 2)) //Pokud neni registarce v siti
                    {
                        signal = false;
                    } else // Pokud je registrovan v domaci siti
                    {
                        signal = true;
                    }
                } else if (Response.startsWith("+CMEE: 21", 2)) // Selhalo SPI
                {
                    komunikace = false;
                } else if(Response.startsWith("^SIND:",2))           // Aktualni cas sync z GSM
               {
                   nastaveniCasu(Response);
                   
               }
                else if(Response.startsWith("^SBV:",2)){
                    docas=Response;
                }
            }
        };
       // ATsend("AT+CPIN=2206\r");
        ATsend("ATZ\r");
        ATsend("AT^SIND=nitz,1");
        ATsend("AT^SCFG=\"Userware/Watchdog\",1");
       // ATsend("AT^SCFG=\"AutoExec\",1,1,2,5,\"AT+CPAS\",\"000:05:00\"\r");
        inicializacePort();
    }

    /**
     * Metoda na poslani ATCommandu - nastaveno zpozdeni 1s - pro pripadne
     * zpracovani prikazu (mozna zkratit)
     *
     * @param ATprikaz ATCommand
     */
    public void ATsend(String ATprikaz) {
        try {
            at.send(ATprikaz, listener);
            Thread.sleep(100L);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } catch (ATCommandFailedException ex) {
            ex.printStackTrace();
        } catch (IllegalStateException ex) {
            ex.printStackTrace();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Metoda na vytvoreni uzivatelskeho profilu - spoustena pouze, pokud profil
     * jiz neexistuje
     *
     */
    public void inicializace() {
        ATsend("ATE0\r");
        ATsend("AT+CMEE=1\r");          // Chybovy vypis nastaven na ciselny vypis
        ATsend("AT+CPBW=1,\"+420604450956\",145, \"JA\"\r");        // Ulozeni cisla jedna (jakoby zachranka)
        ATsend("AT+CPBW=2,\"\",145, \"Doktor\"\r");         // Cislo na doktora
        ATsend("AT+CPBW=3,\"+420604450956\",145, \"Technik\"\r");        // Ulozeni cisla na technika
        ATsend("AT+CMGF=1\r");      // Nastaveni textoveho modu SMS
        ATsend("AT^SSYNC=2\r");        // Nastaveni LED diody
        ATsend("AT^SCFG=\"PowerSaver/Mode9/timeout\",1000\r");         // NAstaveni zpozdeni prenuti zpet do sleepu po poslednim znaku - ted nastaveno na 1 s
        ATsend("AT^SCFG=\"AutoExec\",1,1,2,5,\"AT+CFUN?\",\"001:05:00\"\r");
        ATsend("AT&W\r");                       // ulozeni do profilu
        ATsend("AT+CREG?\r");
        poslaniSMS("Init");
    }

    /**
     * Metoda na poslani sms
     *
     * @param text k poslani
     *
     */
    public void poslaniSMS(String text) {
        ATsend("AT+CMGS=\"+420604450956\"\r");   // Cislo na ktere bude poslana SMS
        ATsend(text + '\032');  // TExt SMS zpravy
    }

    /**
     * Metoda na nasteveni vstupnich a vystupnich pinu
     *
     * @throws vyjimku pri problemu otevereni vstupniho portu
     *
     */
    public void inicializacePort() throws IOException {
        vstupniPin = new Vector(2);        // Vektor vstupnich pinu
        vstupniPin.addElement("GPIO4");      // Pridan pin cislo 4
        // PRIDAT GPIO5 signalizace od ATmegy o problemu
        // vstupniPin.addElement("GPIO5");
        vstup = new InPort(vstupniPin);
        vystupniPin = new Vector(3);
         uroven = new Vector(3);
        vystupniPin.addElement("GPIO5");
        
        uroven.addElement(Integer.valueOf("1"));
        vystupniPin.addElement("GPIO6");
        uroven.addElement(Integer.valueOf("0"));
        vystupniPin.addElement("GPIO7");
        uroven.addElement(Integer.valueOf("1"));
        
        vystup = new OutPort(vystupniPin, uroven);
        vstup.addListener(vstupListener = new InPortListener() {           // Pridani listeneru 

            public void portValueChanged(int value) {        // metoda na zachyceni zmeny hodnoty
                try {
                    Thread.sleep(100);      // Prodleva pro pirpadne ustaleni signalu - smazani metastability
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }      // Prodleva pro pirpadne ustaleni signalu - smazani metastability
                if (value <2) {
                    ATsend("ATD+420604450956\r"); //Volani pri padu
                }
                else if(value==3)
                {
                    ATsend("AT+CFUN=1,0\r");
                    otevritSPI();
                }



            }
        });
    }
    
    /**
     *Pri zmene sbernice
     */
    public void zmenaPinu(boolean smer) throws IOException
    {
        if(smer)
        {
            vystup.release();
            vystupniPin.removeElement("GPIO6");
            uroven.setElementAt(Integer.valueOf("1"),0);
            vystup=new OutPort(vystupniPin,uroven);
            vstup.release();
            vstup.removeListener(vstupListener);
            vstupniPin.addElement("GPIO6");
            vstup = new InPort(vstupniPin);
            vstup.addListener(vstupListener);
        }
        else
        {
            vstup.release();
            vstup.removeListener(vstupListener);
            vstupniPin.removeElement("GPIO6");
            vstup = new InPort(vstupniPin);
            vstup.addListener(vstupListener);
            vystupniPin.addElement("GPIO6");
            //vystupniPin.addElement("GPIO6");
            uroven.setElementAt(Integer.valueOf("0"),1);
            vystup = new OutPort(vystupniPin, uroven);
        }
    }
    /**
     * Nastaveni pinu s pozastavenim na ustaleni pinu
     *
     * @param uroven pozadovana uroven vystupniho pinu
     * @throws InterruptedException pri preruseni uspani vlakna (z duvodu cekani
     * na ustaleni)
     */
    public void setPin(int uroven) throws IOException {
        try {
            vystup.setValue(uroven);
            Thread.sleep(1000);      // Ustaleni
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Metoda na test desky - pokud vraceno false generace resetu a poslani SMS
     *
     */
    public void reset() {
        try {
            setPin(1);
            setPin(5);
        } catch (IOException ex) {
            ex.printStackTrace();           // !!!! Mozna posilat exception ven jako u vsech ostatnic
        }

    }

    /**
     * Metoda na zjisteni, zda je modul zaregistrovan v siti
     *
     * @return signal stav registrace v siti
     */
    public boolean testSignalu() {
        ATsend("AT+CREG?\r");

        return signal;
    }

    /**
     * Metoda na nastaveni pripojeni GPRS
     *
     */
    public void nastaveniPripojeni() {
        ATsend("AT^SJNET=\"gprs\",\"wap.t-mobile.cz\",\"wap\",\"wap\",,0\r");       // Nastaveni pripojeni GPRS
    }

    public void otevritSPI() {
        try {
            setPin(4);
            setPin(5);
            zmenaPinu(true);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        ATsend("AT^SSPI=1020,0000,0000,0000 <1000010>\r");      // Pouze request na 16 bajtu 

    }
    /**
     *Metoda na synchronizaci casu s GSM siti, pokud neni sit (prip.jiny problem), je pouzit aktualni cas modemu
     */
    public void nastaveniCasu(String aktualniCas)
    {
        String temp=null;
        log.zapis("HODINY"+aktualniCas,typZapisu.Informativni);
        try{
            temp=aktualniCas.substring(14,32);
            ATsend("AT+CCLK="+aktualniCas+"\r");        
           
        }catch(IndexOutOfBoundsException ex){
           log.zapis("Synchronizace s GSM se nepovedla. Cas nastaven dle interniho.",typZapisu.Chybovy); 
        }
    }
    
    /**
     *Metoda na kontrolu napeti baterie - pri nizkem informuje uzivatele pomoci SMS
     */
    private int kontrolaBaterie(){
       // docas=new String(napeti);
        napetiBaterie=Integer.parseInt(docas.substring(8,12));
        if(napetiBaterie<4000)
        {
            poslaniSMS("Baterie slaba. Vymente ji");
        }
        return napetiBaterie;
    }
    /*
     *Nacteni napeti baterie
     */
    public String getNapeti()
    {
        ATsend("AT^SBV\r");
        kontrolaBaterie();
        return (docas.substring(8,12));
    }
    
   
}
